﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace BenchMark
{
    class BenchMark
    {
        const int ARR_SIZE = 3000;
        Random randomizer = new Random();

        static void Main(string[] args)
        {
            BenchMark benchmark = new BenchMark();
            benchmark.MemoryLocality();
        }


        private void MemoryLocality()
        {
            //Number[][] arr = new Number[3000][];
            Number[][] arr = CreateJaggedArray<Number[][]>(3000, 3000);

            //Add some values over 100
            for (int i = 0; i < ARR_SIZE; i++)            
                arr[GetNextRandom(0, 2999)][GetNextRandom(0, 2999)].Value = GetNextRandom(101, 1000); 
            
            Stopwatch stopper = new Stopwatch();

            stopper.Start();
            IThenN(arr);
            stopper.Stop();
            Console.WriteLine("IThenN - Took " + stopper.ElapsedMilliseconds);

            stopper.Start();
            NThenI(arr);
            stopper.Start();
            Console.WriteLine("IThenN - Took " + stopper.ElapsedMilliseconds);
        }

        private int GetNextRandom(int min, int max)
        {
            return randomizer.Next(min, max);
        }

        private static void IThenN(Number[][] arr)
        {
            int counter = 0;

            for (int i = 0; i < arr.Length; i++)
            {
                for (int n = 0; n < arr.Length; n++)
                {
                    if (arr[i][n].Value > 100)
                    {
                        counter++;
                    }
                }
            }
        }


        private static void NThenI(Number[][] arr)
        {
            int counter = 0;

            for (int i = 0; i < arr.Length; i++)
            {
                for (int n = 0; n < arr.Length; n++)
                {
                    if (arr[n][i].Value > 100)
                    {
                        counter++;
                    }
                }
            }
        }


        #region helper methods
        
        static T CreateJaggedArray<T>(params int[] lengths)
        {
            return (T)InitializeJaggedArray(typeof(T).GetElementType(), 0, lengths);
        }


        static object InitializeJaggedArray(Type type, int index, int[] lengths)
        {
            Array array = Array.CreateInstance(type, lengths[index]);
            Type elementType = type.GetElementType();

            if (elementType != null)
            {
                for (int i = 0; i < lengths[index]; i++)
                {
                    array.SetValue(InitializeJaggedArray(elementType, index + 1, lengths), i);
                }
            }

            return array;
        } 

        #endregion

        public struct Number
        {
            public int Value { get; set; }

            public override string ToString()
            {
                return Value.ToString();
            }
        }

    }
}
